package com.kitty.game.scene;

import com.kitty.common.thread.NamedThreadFactory;
import com.kitty.game.config.GameMap;
import com.kitty.game.role.model.Role;
import com.kitty.game.scene.aoi.AOI;
import com.kitty.game.scene.aoi.Scene;
import com.kitty.mina.message.Message;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 场景管理器
 */
public enum SceneManager {
    INSTANCE;



    private static final int CORE_SIZE = 32;

    private final AtomicInteger atomicInteger = new AtomicInteger();
    /**
     * task worker pool
     */
    private static final List<TaskWorker> workerPool = new ArrayList<>();
    /**
     * 启动时候把每个地图都初始化一个Scene
     */
    //可能有问题  --001
    private static final Map<Integer, AOI> scenes = new HashMap<>();

    public void initiate(List<GameMap> maps) {
        maps.forEach(gameMap -> {
            AOI scene = new Scene();
            scene.setId(atomicInteger.getAndIncrement());
            scenes.put(gameMap.getId(), scene);
        });
    }

    static {
        for (int i = 1; i <= CORE_SIZE; i++) {
            TaskWorker worker = new TaskWorker(i);
            workerPool.add(worker);
            new NamedThreadFactory("scene_" + i).newThread(worker).start();
        }
    }

    private AOI getScene(int mapId) {
        return scenes.get(mapId);
    }

    /**
     * 进入地图
     */
    public void enterMap(int mapId, Role role) {
        AOI scene = getScene(mapId);
        acceptTask(scene.getId(), () -> scene.enter(role));
    }

    /**
     * 离开地图
     */
    public void leaveMap(int mapId, Role role) {
        AOI scene = getScene(mapId);
        acceptTask(scene.getId(), () -> scene.leave(role.getUid()));
    }

    /**
     * 移动位置
     */
    public void movePosition(Role role) {
        int mapId = role.getPos().getMapId();
        AOI scene = getScene(mapId);
        acceptTask(scene.getId(), () -> scene.move(role));
    }

    /**
     * AOI 通用局域广播消息
     */
    public void sendMessages(Role role, Message...messages) {
        AOI scene = getScene(role.getPos().getMapId());
        acceptTask(scene.getId(), () -> scene.sendMessages(role, messages));
    }

    public void acceptTask(int sceneId, Runnable task) {
        if (task == null) {
            return;
        }
        int size = workerPool.size();
        int index = sceneId % size;
        workerPool.get(index).addTask(task);
    }


    private static class TaskWorker implements Runnable {
        /**
         * worker id
         */
        private int id;
        /**
         * task consumer queue
         */
        private BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();

        TaskWorker(int index) {
            this.id = index;
        }

        void addTask(Runnable task) {
            this.taskQueue.add(task);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Runnable task = taskQueue.take();
                    task.run();
                } catch (Exception e) {

                }
            }
        }
    }
}
